﻿using AppEszköz.Cryptography;
using Microsoft.Win32;
using System;

namespace AppEszköz.Config
{
    internal class SecureRegistry
    {
        private string passPhrase;
        private string saltValue;
        private string subKey1;
        private string subKey2;
        private string subKey3;
        private string subKey4;

        public SecureRegistry()
        {
            this.passPhrase = "myUnsafeKey";
            this.saltValue = "myUnsafeSalt";
        }

        public SecureRegistry(string passPhrase, string saltValue, string subKey1, string subKey2, string subKey3,
            string subKey4)
        {
            this.passPhrase = passPhrase;
            this.saltValue = saltValue;
            this.subKey1 = subKey1;
            this.subKey2 = subKey2;
            this.subKey3 = subKey3;
            this.subKey4 = subKey4;
        }

        internal void WriteToRegistry(string key, string value, bool shouldEncrypt)
        {
            this.CheckFields();
            RegistryKey subKey =
                Registry.LocalMachine.OpenSubKey(this.subKey1, true)
                    .CreateSubKey(this.subKey2)
                    .CreateSubKey(this.subKey3)
                    .CreateSubKey(this.subKey4);
            if (shouldEncrypt)
                value = this.EncryptIt(value);
            subKey.SetValue(key, (object) value);
        }

        internal string ReadFromRegistry(string key, bool shouldDecrypt)
        {
            this.CheckFields();
            string str = string.Empty;
            string encryptedText;
            try
            {
                encryptedText =
                    (string)
                        Registry.LocalMachine.OpenSubKey(this.subKey1)
                            .OpenSubKey(this.subKey2)
                            .OpenSubKey(this.subKey3)
                            .OpenSubKey(this.subKey4)
                            .GetValue(key);
                if (encryptedText == null)
                    return (string) null;
            }
            catch (Exception ex)
            {
                throw new Exception(
                    "Unable to read registry key: " + this.subKey1 + "\\" + this.subKey2 + "\\" + this.subKey3 + "\\" +
                    this.subKey4 + "\\" + key, ex);
            }
            if (shouldDecrypt)
            {
                try
                {
                    encryptedText = this.DecryptIt(encryptedText);
                }
                catch (Exception ex)
                {
                    throw new Exception(
                        "Unable to decrypt registry key: " + this.subKey1 + "\\" + this.subKey2 + "\\" + this.subKey3 +
                        "\\" + this.subKey4 + "\\" + key, ex);
                }
            }
            return encryptedText;
        }

        private void CheckFields()
        {
            if (this.subKey1 == null || this.subKey1.Length == 0)
                throw new MissingFieldException("SecureRegistry", "subKey1");
            if (this.subKey2 == null || this.subKey2.Length == 0)
                throw new MissingFieldException("SecureRegistry", "subKey2");
            if (this.subKey3 == null || this.subKey3.Length == 0)
                throw new MissingFieldException("SecureRegistry", "subKey3");
            if (this.subKey4 == null || this.subKey4.Length == 0)
                throw new MissingFieldException("SecureRegistry", "subKey4");
        }

        private string EncryptIt(string plainText)
        {
            return RijndaelEncryption.Encrypt(plainText, this.passPhrase, this.saltValue, "MD5", 2, "@1B2c3D4e5F6g7H8",
                256);
        }

        private string DecryptIt(string encryptedText)
        {
            return RijndaelEncryption.Decrypt(encryptedText, this.passPhrase, this.saltValue, "MD5", 2,
                "@1B2c3D4e5F6g7H8", 256);
        }
    }
}